#include "DVRCommonPCH.h"
#include "OccupancyBrick.h"

using namespace hiveDVR;

//**************************************************************************************************
//FUNCTION:
void COccupancyBrick::init(const std::shared_ptr<CVolume> vpVolume)
{
	__generateOccupiedBoxSet(vpVolume);
	__generateInstanceMatrices();
}

//**************************************************************************************************
//FUNCTION:
glm::vec3 COccupancyBrick::getNormalizedBoxSize() const
{
	return 1.0f / m_NumBricks;
}

//**************************************************************************************************
//FUNCTION:
void COccupancyBrick::__generateOccupiedBoxSet(const std::shared_ptr<CVolume> vpVolume)
{
	m_NumBricks.x = __calculateNumberBrick(vpVolume->getWidth());
	m_NumBricks.y = __calculateNumberBrick(vpVolume->getHeight());
	m_NumBricks.z = __calculateNumberBrick(vpVolume->getDepth());

	for (size_t x = 0; x < m_NumBricks.x; ++x)
	{
		for (size_t y = 0; y < m_NumBricks.y; ++y)
		{
			for (size_t z = 0; z < m_NumBricks.z; ++z)
			{
				glm::vec3 BoxMin = glm::vec3(static_cast<float>(x) / m_NumBricks.x, static_cast<float>(y) / m_NumBricks.y, static_cast<float>(z) / m_NumBricks.z);
				glm::vec3 BoxMax = glm::vec3(static_cast<float>(x + 1) / m_NumBricks.x, static_cast<float>(y + 1) / m_NumBricks.y, static_cast<float>(z + 1) / m_NumBricks.z);
				CAABB SampleBox(BoxMin, BoxMax);

				float SampleValue = vpVolume->sampleAverageData(SampleBox);
				if (SampleValue >= EMPTY_THRESHOLD) m_OccupiedBoxSet.push_back(SampleBox);
			}
		}
	}
}

//**************************************************************************************************
//FUNCTION:
void COccupancyBrick::__generateInstanceMatrices()
{
	for (size_t i = 0; i < m_OccupiedBoxSet.size(); ++i)
	{
		CTransform Transform;
		glm::vec3 TranslationFactor = (m_OccupiedBoxSet[i].getMin() + m_OccupiedBoxSet[i].getMax()) * 0.5f - 0.5f;
		glm::vec3 ScalingFactor = m_OccupiedBoxSet[i].getMax() - m_OccupiedBoxSet[i].getMin();
		glm::vec2 RotationFactor = { 0.0f, 0.0f };
		Transform.update(TranslationFactor, ScalingFactor, RotationFactor);
		m_TransformSet.push_back(Transform);
	}
	outputInfo("Num of Occupied Boxes: " + std::to_string(m_OccupiedBoxSet.size()) + "\n");
}

//**************************************************************************************************
//FUNCTION:
size_t COccupancyBrick::__calculateNumberBrick(size_t vVolumeDimension) const
{
	return static_cast<size_t>(ceil(static_cast<float>(vVolumeDimension) / BRICKSIZE));
}
